package com.hspedu.synchronized_;


/**
 * @Author Stringzhua
 * @Date 2024/3/15 13:35
 * description:
 * 使用多线程,模拟三个窗口同时售票100张
 * synchronized 解决窗口买票超卖问题
 */
public class SellTicket {
    public static void main(String[] args) {
        //测试
//        SellTicket01 sellTicket01 = new SellTicket01();
//        SellTicket01 sellTicket02 = new SellTicket01();
//        SellTicket01 sellTicket03 = new SellTicket01();
//
//        //这里出现了票超卖情况
//        sellTicket01.start();//启动售票线程
//        sellTicket02.start();//启动售票线程
//        sellTicket03.start();//启动售票线程


//        System.out.println("===使用实现接口的方式来售票===");
        SellTicket03 sellTicket03 = new SellTicket03();

        new Thread(sellTicket03).start();//第1个线程窗口
        new Thread(sellTicket03).start();//第2个线程窗口
        new Thread(sellTicket03).start();//第3个线程窗口
    }
}


//实现接口方式,使用synchronized实现线程同步
class SellTicket03 implements Runnable {
    private int ticketNum = 100;//让多个线程共享 ticketNum

    private boolean loop = true;//控制run方法变量

    Object object = new Object();

    //同步方法(静态的)的锁为当前类本身
    //1. public synchronized static void m1(){}的锁加在SellTicket03.class
    //2.如果在静态方法中实现一个同步的代码块
    /*
    *  synchronized (SellTicket03.class) {
        System.out.println("m2");
        }
    * */
    public synchronized static void m1() {
    }

    public static void m2() {
        synchronized (/*this*/SellTicket03.class) {
            System.out.println("m2");
        }
    }

    /*
     * 1.public synchronized void sell() {} 是一个同步方法
     * 2.这时这个锁在this对象
     * 3.也可在代码块上写synchronized,同步代码块,互斥锁还是加在this对象中
     * */

    public /*synchronized*/ void sell() {//同步方法锁,在同一个时刻,只能有一个线程来执行sell方法
        synchronized (/*this*/object) {
            if (ticketNum <= 0) {
                System.out.println("售票结束....");
                loop = false;
                return;
            }
            //休眠50ms,模拟人的休息
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口" + Thread.currentThread().getName() + "售出了一张票" +
                    "剩余票数=" + (--ticketNum));//1 0 1 -2
        }
    }

    @Override
    public void run() {
        while (loop) {
            sell();
        }
    }
}


//使用Thread方式
//new SellTicket01.start();
//new SellTicket01.start();
class SellTicket01 extends Thread {
    private static int ticketNum = 100;//让多个线程共享 ticketNum

//    public void m1(){
//        synchronized (this){
//            System.out.println("hello");
//        }
//    }
    @Override
    public void run() {
        while (true) {
            if (ticketNum <= 0) {
                System.out.println("售票结束....");
                break;
            }
            //休眠50ms,模拟人的休息
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口" + Thread.currentThread().getName() + "售出了一张票" +
                    "剩余票数=" + (--ticketNum));
        }
    }
}

